package gui;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.xml.ws.Endpoint;

import security.Encryption;

import entities.Device;
import entities.DeviceType;
import entities.User;

import fileServiceAndroid.FileServiceHost;
import fileServiceWindows.FileServiceImp;
import awWindowsApplication.ConnectionServiceImpService;
import awWindowsApplication.FileIO;

public class WindowsApplication {
	private JFrame frame;//main
	private FileIO fileControl;//main
	private ConnectionServiceImpService cs;//main
	private Device device;//main
	private FileServiceHost fsh;//main
	
	private User user;//during login

	private ArrayList<String> errors = new ArrayList<String>();
	
	
	public static void main(String[] args) {
		new WindowsApplication();
	}
	public WindowsApplication(){		
		fileControl = new FileIO();
		
		fileControl.createHiddenFolder();		
		
		cs = new ConnectionServiceImpService();
		getDeviceInfo();
		fsh = new FileServiceHost(this);
		startAndroidFileService();
		startWindowsFileService();
		
		initialize();			
		frame.setContentPane(new Login(this).getPanel());
	}
	
	private void initialize(){
		frame = new JFrame();
		frame.setBounds(100,100,818,647);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);
		frame.setResizable(false);
		frame.setVisible(true);
	}
	
	//before login
	public void startWindowsFileService(){
		Endpoint.publish("http://" + device.getIpAddress() + ":2080/fs", new FileServiceImp(this));		
	}
	public void startAndroidFileService(){
		new Thread(fsh).start();
	}

	//after login
	public void deviceAttachedUser(){
		ArrayList<Device> devices = cs.getConnectionServiceImpPort().getDevicesByUser(String.valueOf(user.getId()));
		boolean added = false;
		for(Device d : devices){
			if(d.getUUID().equals(device.getUUID())){
				added = true;
				break;
			}
		}
		if(!added){
			cs.getConnectionServiceImpPort().addUserDevice(device.getUUID(), String.valueOf(user.getId()));
		}
	}
	
	//before login
	private void getDeviceInfo(){
		System.out.println("WindowsApplication: getDeviceInfo()");
		Device device = new Device();
		
		try {
			InetAddress local = InetAddress.getLocalHost();				
			
			device.setUUID(getWindowsMBID());
//			device.setUUID("UBUNTU 12.04");
			device.setDeviceName(local.getHostName());
			device.setIpAddress(local.getHostAddress());
//			device.setIpAddress("192.168.2.147");
			device.setDeviceType(DeviceType.WINDOWS);
		} catch (UnknownHostException e) {e.printStackTrace();}
		ArrayList<String> config = fileControl.getConfigFile();
		String pairKey = "";
		for(int i = 0; i < config.size(); i++){
			String s = config.get(i);
			String[] value = s.split(":");
			if(value[0].equals("rsaexp")){
				pairKey = value[1];
			}
		}
		Device host = cs.getConnectionServiceImpPort().getDeviceByUUID(device.getUUID());
		if(host.getDeviceName().equals("NOTFOUND")){
			cs.getConnectionServiceImpPort().addDevice(device);
			String encPairKey = Encryption.digest(pairKey);
			cs.getConnectionServiceImpPort().insertDevicePair(host.getUUID(), encPairKey);
		}else{
			if(!device.getIpAddress().equals(host.getIpAddress())){
				host.setIpAddress(device.getIpAddress());
			}
			String encPairKey = Encryption.digest(pairKey);
			cs.getConnectionServiceImpPort().updateDevicePair(device.getUUID(), encPairKey);
			device = host;
		}
	
		this.device = device;
	}

	private String getWindowsMBID(){
		/*
		 * This method was retrieved from: http://stackoverflow.com/questions/13435960/
		 */
		String result = "";
	    try {
	    File file = File.createTempFile("realhowto",".vbs");
	    file.deleteOnExit();
	    FileWriter fw = new java.io.FileWriter(file);

	    String vbs =
	    "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
	    + "Set colItems = objWMIService.ExecQuery _ \n"
	    + " (\"Select * from Win32_BaseBoard\") \n"
	    + "For Each objItem in colItems \n"
	    + " Wscript.Echo objItem.SerialNumber \n"
	    + " exit for ' do the first cpu only! \n"
	    + "Next \n";

	    fw.write(vbs);
	    fw.close();
	    Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
	    BufferedReader input =
	    new BufferedReader
	    (new InputStreamReader(p.getInputStream()));
	    String line;
	    while ((line = input.readLine()) != null) {
	    result += line;
	    }
	    input.close();
	    }
	    catch(Exception e){
	    e.printStackTrace();
	    }
	    return result.trim();
	}
	
	public RSAPublicKeySpec generatePublicKey(BigInteger exp){
		BigInteger mod = BigInteger.valueOf(9333546322778663l);			
		
		return new RSAPublicKeySpec(mod, exp);
	}
	public RSAPrivateKeySpec generatePrivateKey(BigInteger exp){
		BigInteger mod = BigInteger.valueOf(9333546322778663l);
		
		return new RSAPrivateKeySpec(mod, exp);
	}
	
	public JFrame getFrame(){
		return frame;
	}	
	public FileIO getFileIO(){
		return fileControl;
	}
	public ConnectionServiceImpService getCSEP(){
		return cs;
	}
	public Device getDevice(){
		return device;
	}
	public User getUser(){
		return user;
	}
	public void setUser(User u){
		this.user = u;
	}
	public void setDevice(Device device){
		this.device = device;
	}
	
	
	public ArrayList<String> getErrors(){
		return errors;
	}
	public void addError(String error){
		errors.add(error);
	}
	public void clearErrors(){
		errors = new ArrayList<String>();
	}
}
